//
// Ephi - simulation of magnetic fields and particles
// Copyright (C) 2007 Indrek Mandre <indrek(at)mare.ee>
// For more information please see http://www.mare.ee/indrek/ephi/
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "ephi.hpp"

#include <string>

// visualize coil fields
// For example generate data and visualize it:
// ./coilgen -n 1 -m 100 -r 0.15 -w 0.035 -g 0.65x0.65 -e -s 0.01
// ./itest

static void calcsome (const std::string& bn, const CoilData& cd, Statics& statics, ElectroDynamics& dyn)
{
  Screen screen(800, 800, cd.coil_radius * 5, cd.coil_radius * 5);
  Scene scene(dyn);

  if ( cd.bmapemap || cd.cubic_bmapemap )
    {
      scene.calc (screen, Scene::CALC_EFIELD);

      scene.set_coloring (0);
      scene.render_map (screen);
      screen.write (bn + "_e.bmp");

      scene.set_coloring (32, true);
      scene.render_map (screen);
      screen.write (bn + "_e_log.bmp");

      scene.set_coloring (1);
      scene.render_lic (screen);
      screen.write (bn + "_e_lic.bmp");

      scene.set_coloring (0, true);
      scene.render_lic (screen);
      screen.write (bn + "_e_lic_logcolor.bmp");
    }

  if ( cd.bmap || cd.bmapemap || cd.cubic_bmap || cd.cubic_bmapemap )
    {
      scene.calc (screen);

      scene.set_coloring (0);
      scene.render_map (screen);
      screen.write (bn + "_b.bmp");

      scene.set_coloring (32, true);
      scene.render_map (screen);
      screen.write (bn + "_b_log.bmp");

      scene.set_coloring (1);
      scene.render_lic (screen);
      screen.write (bn + "_b_lic.bmp");

      scene.set_coloring (0, true);
      scene.render_lic (screen);
      screen.write (bn + "_b_lic_logcolor.bmp");
    }

}

int main (int argc, char *argv[])
{
  CoilData cd;
  const char *path = argc == 1 ? "out.cgen" : argv[1];
  if ( !cd.load (path) )
    {
      fprintf (stderr, "%s: failed to load %s!\n", argv[0], path);
      exit(-1);
    }

#if 0
  {
  Statics statics;
  ElectroDynamics dyn(statics);
  make_coil (statics, vect3d(0, 0, 0), vect3d(1, 0, 0), 0.15, 0.035, 1, 1e-7, 1);
  calcsome ("itest_dc", cd, statics, dyn);
  }
#endif

  if ( cd.bmap || cd.bmapemap )
    {
      Statics statics;
      ElectroDynamics dyn(statics);
      statics.addStaticElement (new StaticCIL(cd, vect3d(0, 0, 0), vect3d(1, 0, 0), 1, 1e-7));
      if ( (cd.flags & coilgen_header::IS_COILPAIR) && (cd.flags & coilgen_header::IS_OPPOSING_COILPAIR) &&
          cd.coil_radius * 2 <= cd.coilpair_distance )
        {
          printf ("Opposing coilpair with enough distance, composing a cube polywell\n");
          statics.addStaticElement (new StaticCIL(cd, vect3d(0, 0, 0), vect3d(0, 1, 0), 1, 1e-7));
          statics.addStaticElement (new StaticCIL(cd, vect3d(0, 0, 0), vect3d(0, 0, 1), 1, 1e-7));
        }
      calcsome ("itest_li", cd, statics, dyn);
    }

  if ( cd.bmap || cd.bmapemap )
    {
      Statics statics;
      ElectroDynamics dyn(statics);
      statics.addStaticElement (new StaticCINN(cd, vect3d(0, 0, 0), vect3d(1, 0, 0), 1, 1e-7));
      if ( (cd.flags & coilgen_header::IS_COILPAIR) && (cd.flags & coilgen_header::IS_OPPOSING_COILPAIR) &&
          cd.coil_radius * 2 <= cd.coilpair_distance )
        {
          printf ("Opposing coilpair with enough distance, composing a cube polywell\n");
          statics.addStaticElement (new StaticCINN(cd, vect3d(0, 0, 0), vect3d(0, 1, 0), 1, 1e-7));
          statics.addStaticElement (new StaticCINN(cd, vect3d(0, 0, 0), vect3d(0, 0, 1), 1, 1e-7));
        }
      calcsome ("itest_nn", cd, statics, dyn);
    }

  if ( cd.cubic_bmap || cd.cubic_bmapemap )
    {
      Statics statics;
      ElectroDynamics dyn(statics);
      statics.addStaticElement (new StaticCICU(cd, vect3d(0, 0, 0), vect3d(1, 0, 0), 1, 1e-7));
      if ( (cd.flags & coilgen_header::IS_COILPAIR) && (cd.flags & coilgen_header::IS_OPPOSING_COILPAIR) &&
          cd.coil_radius * 2 <= cd.coilpair_distance )
        {
          printf ("Opposing coilpair with enough distance, composing a cube polywell\n");
          statics.addStaticElement (new StaticCICU(cd, vect3d(0, 0, 0), vect3d(0, 1, 0), 1, 1e-7));
          statics.addStaticElement (new StaticCICU(cd, vect3d(0, 0, 0), vect3d(0, 0, 1), 1, 1e-7));
        }
      calcsome ("itest_cu", cd, statics, dyn);
    }

  return 0;
}

